package com.zjmzxfzhl.integrityconstraint.service;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.zjmzxfzhl.integrityconstraint.config.IntegrityConstraintProperties;
import com.zjmzxfzhl.integrityconstraint.entity.IntegrityConstraint;
import com.zjmzxfzhl.integrityconstraint.pojo.ToCheck;
import com.zjmzxfzhl.integrityconstraint.utils.JacksonUtil;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 业务完整性验证抽象类
 *
 * @author 庄金明
 */
@Slf4j
public abstract class AbstractIntegrityConstraintService implements IntegrityConstraintService {
    protected final IntegrityConstraintProperties integrityConstraintProperties;

    public AbstractIntegrityConstraintService(IntegrityConstraintProperties integrityConstraintProperties) {
        this.integrityConstraintProperties = integrityConstraintProperties;
    }

    protected Boolean commonCheck(List<IntegrityConstraint> integrityConstraints, List<ToCheck> toChecks) {
        if (toChecks == null || toChecks.isEmpty()) {
            return false;
        }

        Map<String, IntegrityConstraint> integrityConstraintMap = new HashMap<>();
        integrityConstraints.forEach(item -> integrityConstraintMap.put(item.getVerifyType(), item));

        for (int i = 0; i < toChecks.size(); i++) {
            ToCheck toCheck = toChecks.get(i);
            IntegrityConstraint integrityConstraint = integrityConstraintMap.get(toCheck.getType());
            if (integrityConstraint == null) {
                log.info("cann't find verifyTyp={} in cache", integrityConstraint.getBusinessKey(), toCheck.getType());
                return false;
            }
            IntegrityConstraint integrityConstraintBefore;
            if (i > 0) {
                integrityConstraintBefore = integrityConstraintMap.get(toChecks.get(i - 1).getType());
                if (integrityConstraintBefore.getCreateTime() > integrityConstraint.getCreateTime()) {
                    log.info("businessKey={},verifyTyp={} before verifyTyp={}", integrityConstraint.getBusinessKey(),
                            integrityConstraint.getVerifyType(), integrityConstraintBefore.getVerifyType());
                    return false;
                }
            }

            // 验证信息已超时
            Long expire = integrityConstraint.getExpire() > 0 ? integrityConstraint.getExpire() : integrityConstraintProperties.getExpire() * 1000;
            if (System.currentTimeMillis() - integrityConstraint.getCreateTime() > expire) {
                log.info("businessKey={}, verifyTyp={} is expired", integrityConstraint.getBusinessKey(), integrityConstraint.getVerifyType());
                return false;
            }

            Object toCheckData = toCheck.getData();
            Object object = JacksonUtil.strToObj(integrityConstraint.getJsonData(), toCheckData.getClass());
            if (!Objects.equals(toCheckData, object)) {
                log.info("businessKey={}, verifyTyp={} invalid data={}", integrityConstraint.getBusinessKey(),
                        integrityConstraint.getVerifyType(), JacksonUtil.objToStr(toCheckData, JsonInclude.Include.NON_EMPTY));
                return false;
            }
        }
        return true;
    }
}
